﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Streambolics.Gui;

namespace Streambolics.Tablet
{
    public class WMTouchEventArgs : System.EventArgs
    {
        // Private data members
        private int x;                  // touch x client coordinate in pixels
        private int y;                  // touch y client coordinate in pixels
        private int id;                 // contact ID
        private int mask;               // mask which fields in the structure are valid
        private int flags;              // flags
        private int time;               // touch event time
        private int contactX;           // x size of the contact area in pixels
        private int contactY;           // y size of the contact area in pixels

        // Access to data members
        public int LocationX
        {
            get
            {
                return x;
            }
            set
            {
                x = value;
            }
        }
        public int LocationY
        {
            get
            {
                return y;
            }
            set
            {
                y = value;
            }
        }
        public int Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }
        public int Flags
        {
            get
            {
                return flags;
            }
            set
            {
                flags = value;
            }
        }
        public int Mask
        {
            get
            {
                return mask;
            }
            set
            {
                mask = value;
            }
        }
        public int Time
        {
            get
            {
                return time;
            }
            set
            {
                time = value;
            }
        }
        public int ContactX
        {
            get
            {
                return contactX;
            }
            set
            {
                contactX = value;
            }
        }
        public int ContactY
        {
            get
            {
                return contactY;
            }
            set
            {
                contactY = value;
            }
        }
        public bool IsPrimaryContact
        {
            get
            {
                return (flags & TouchApi.TOUCHEVENTF_PRIMARY) != 0;
            }
        }

        public WMTouchEventArgs ()
        {
        }
    }



    public partial class TouchAwareUserControl : StandardUserControl
    {
        #region Static Optimizations

        private static bool _TouchApiAvailable = true;
        private static int _TouchStructureSize;

        #endregion

        #region WIN32 API

        // TODO : All this should go to TouchApi.cs

        #endregion

        private bool _TouchEnabled;


        public TouchAwareUserControl ()
        {
            InitializeComponent ();
            _TouchStructureSize = Marshal.SizeOf (new TouchApi.TOUCHINPUT ());
        }

        public event EventHandler<WMTouchEventArgs> TouchDown;
        public event EventHandler<WMTouchEventArgs> TouchUp;  
        public event EventHandler<WMTouchEventArgs> TouchMove;

        protected virtual void OnTouchDown (WMTouchEventArgs e)
        {
            if (TouchDown != null)
            {
                TouchDown (this, e);
            }
        }

        protected virtual void OnTouchUp (WMTouchEventArgs e)
        {
            if (TouchUp != null)
            {
                TouchUp (this, e);
            }
        }

        protected virtual void OnTouchMove (WMTouchEventArgs e)
        {
            if (TouchMove != null)
            {
                TouchMove (this, e);
            }
        }

        protected override void OnLoad (EventArgs e)
        {
            base.OnLoad (e);

            if (_TouchApiAvailable)
            {
                ulong ulFlags = 0;
                try
                {
                    _TouchEnabled = TouchApi.RegisterTouchWindow (this.Handle, ulFlags);
                }
                catch
                {
                    _TouchApiAvailable = false;
                }
            }
        }

        protected override void WndProc (ref Message m)
        {
            bool handled;
            switch (m.Msg)
            {
                case TouchApi.WM_TOUCH:
                //case TouchApi.WM_TOUCHMOVE:
                //case TouchApi.WM_TOUCHUP:
                    try
                    {
                        handled = DecodeTouch (ref m);
                    }
                    catch
                    {
                        handled = false;
                    }
                    break;
                default:
                    handled = false;
                    break;
            }

            // Call parent WndProc for default message processing.
            base.WndProc (ref m);

            if (handled)
            {
                m.Result = new System.IntPtr (1);
            }
        }

        private bool DecodeTouch (ref Message m)
        {
            int inputCount = m.WParam.ToInt32 () & 0xffff;

            TouchApi.TOUCHINPUT[] inputs = new TouchApi.TOUCHINPUT[inputCount];
            if (!TouchApi.GetTouchInputInfo (m.LParam, inputCount, inputs, _TouchStructureSize))
            {
                return false;
            }

            bool handled = false;

            for (int i = 0; i < inputCount; i++)
            {
                TouchApi.TOUCHINPUT ti = inputs[i];

                WMTouchEventArgs te = new WMTouchEventArgs ();

                te.ContactY = ti.cyContact / 100;
                te.ContactX = ti.cxContact / 100;
                te.Id = ti.dwID;
                Point pt = PointToClient (new Point (ti.x / 100, ti.y / 100));
                te.LocationX = pt.X;
                te.LocationY = pt.Y;
                te.Time = ti.dwTime;
                te.Mask = ti.dwMask;
                te.Flags = ti.dwFlags;

                if ((ti.dwFlags & TouchApi.TOUCHEVENTF_DOWN) != 0)
                {
                    OnTouchDown (te);
                    handled = true;
                }

                if ((ti.dwFlags & TouchApi.TOUCHEVENTF_MOVE) != 0)
                {
                    OnTouchMove (te);
                    handled = true;
                }

                if ((ti.dwFlags & TouchApi.TOUCHEVENTF_UP) != 0)
                {
                    OnTouchUp (te);
                    handled = true;
                }
            }

            // IMHO should not do this since the default wndproc will
            // TouchApi.CloseTouchInputHandle (m.LParam);

            return handled;
        }

   
    }
}
